package com.liuqi.knet.remoting.transport.dispatcher.handler;

import com.liuqi.knet.remoting.Channel;
import com.liuqi.knet.remoting.ChannelHandler;
import com.liuqi.knet.remoting.RemotingException;
import com.liuqi.knet.remoting.exchange.Event;
import com.liuqi.knet.remoting.transport.AbstractChannelHandlerDelegate;
import com.liuqi.loggers.api.Logger;
import com.liuqi.loggers.facade.LoggersFacade;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * 建立连接负载校验,
 *
 * 连接不能大于 {@link #accepts}
 *
 * @author liuqi
 * @date 2025/2/8 17:56
 **/
public class AcceptsLoadHandler extends AbstractChannelHandlerDelegate {

    private static final Logger logger = LoggersFacade.getLogger(AcceptsLoadHandler.class);

    /**
     * 服务端最大可连接个数
     */
    public final int accepts;

    /**
     * 客户端连接缓存
     */
    private final LinkedBlockingQueue<Object> channels = new LinkedBlockingQueue<Object>();

    public AcceptsLoadHandler(ChannelHandler handler, int accepts) {
        super(handler);
        this.accepts = accepts;
    }

    @Override
    public void connected(Channel channel) throws RemotingException {
        if (accepts > 0 && channels.size() >= accepts) {
            logger.error("关闭客户端连接 " + channel + ", 错误原因: 当前服务端的连接数大于最大配置的连接数: " + accepts);

            Event event = new Event(Event.Type.REJECT_CONNECTION, "服务端连接数已满, 拒绝此次连接");

            // 通知客户端
            channel.send(event, true);

            // close channel
            channel.close();
        }

        if (!channels.contains(channel)) {
            channels.offer(channel);
        }
    }

    @Override
    public void disconnected(Channel channel) throws RemotingException {
        channels.remove(channel);
        handler.disconnected(channel);
    }

    @Override
    public void caught(Channel channel, Throwable exception) throws RemotingException {
        channels.remove(channel);
        handler.caught(channel, exception);
    }

}
